﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using System.Runtime.InteropServices;

namespace VoltcraftControlInterface
{
    [Serializable]
    public class SerializerClass    //CLASS NEEDED TO SAVE PROJECT FILES
    {
        public Dictionary<string, System.IO.MemoryStream> logserialize;
        public Dictionary<string, System.IO.MemoryStream> dmmserialize;
        public Dictionary<string, System.IO.MemoryStream> heatserialize;
        public Dictionary<string, System.IO.MemoryStream> powserialize;
        public Dictionary<string, string> mediumselected;
        public DataTable listofmediums;
    }

    [Serializable]
    public class AppSettings
    {
        public bool AutoSave;
        public bool EmergencyStop;
        public bool ovCurrProtection;
        public Double currLimit;
        public int AutoSaveTimeout;
    }

    public class Parser     //CORE OF THE VICTOR 86C INPUT DATA DECODIFIER
    {
        /* Variable LIST */
        /* INPUT */
        public Byte[] inputBytes;
        /* OUTPUT */
        public string Value; //string value with subunit of measure (e.g. 100 mV, 1000 nF, 2 μA)
        public Double numValue; //numeric value relative to subunit of measure
        public Double RectifiedValue; //numeric value with no subunit (e.g. 100 mV ---> 0.100 V, 1000 nF --> 0.000001 F)
        public bool IsAC;
        public bool IsDC;
        public bool IsMax;
        public bool IsMin;
        public bool IsRel;
        public bool IsHold;
        public bool IsOutOfRange;
        public bool IsAutoSub;
        public string UnitOfMeasure; //Unit of measure
        public string LongUnitOfMeasure; //Not abbreviated unit of measure string. e.g. Voltage, Hertz
        public string ACDC;

        public Parser()
        {
            //Declaration of all variables
            inputBytes = null;
            Value = UnitOfMeasure = LongUnitOfMeasure = ACDC = "";
            numValue = 0;
            RectifiedValue = 0;
            IsAC = IsDC = IsAutoSub = IsHold = IsMax = IsMin = IsOutOfRange = IsRel = false;
        }

        public void UpdateResult()
        {
            if (inputBytes!= null)
            {
                Value = UnitOfMeasure = LongUnitOfMeasure = ACDC = "";
                numValue = 0;
                RectifiedValue = 0;
                IsAC = IsDC = IsAutoSub = IsHold = IsMax = IsMin = IsOutOfRange = IsRel = false;
                string byte7, byte10, byte4, byte11 = "";
                // Retrieving number displayed
                byte7 = Convert.ToString(inputBytes[7], 2).PadLeft(8, '0').Substring(0, 4);
                byte10 = Convert.ToString(inputBytes[10], 2).PadLeft(8, '0').Substring(0, 4);
                byte4 = Convert.ToString(inputBytes[4], 2).PadLeft(8, '0').Substring(0, 4);
                byte11 = Convert.ToString(inputBytes[11], 2).PadLeft(8, '0').Substring(0, 4);
                numValue = Parse7(byte7) + (Parse10(byte10) * 10) + (Parse4(byte4) * 100) + (Parse11(byte11) * 1000);
                numValue *= ParseSign(Convert.ToString(inputBytes[2], 2).PadLeft(8, '0').Substring(1, 2));
                // Setting the decimal point in the number
                int commapos = CommaPos(Convert.ToString(inputBytes[6], 2).PadLeft(8, '0').Substring(0, 4));
                if (commapos == 3)
                {
                    numValue /= 1000;
                    Value = numValue.ToString("F3");
                }
                else if (commapos == 2)
                {
                    numValue /= 100;
                    Value = numValue.ToString("F2");
                }
                else if (commapos == 1)
                {
                    numValue /= 10;
                    Value = numValue.ToString("F1");
                }
                else Value = numValue.ToString("F0");
                RectifiedValue = numValue;
                //Setting the RectifiedValue by getting SubUnit of Measure
                if (ParseSub(Convert.ToString(inputBytes[13], 2).PadLeft(8, '0')) == "m")
                    RectifiedValue /= 1000;
                else if (ParseSub(Convert.ToString(inputBytes[13], 2).PadLeft(8, '0')) == "μ")
                    RectifiedValue /= 1000000;
                //Setting Unit and SubUnit of measure in string Value output
                UnitOfMeasure = ParseMode(Convert.ToString(inputBytes[9], 2).PadLeft(8, '0'));
                if (UnitOfMeasure == "Ω")
                {
                    Value += (" " + ParseOhmMode(Convert.ToString(inputBytes[13], 2).PadLeft(8, '0')) + "Ω");
                    if (ParseOhmMode(Convert.ToString(inputBytes[13], 2).PadLeft(8, '0')) == "k") RectifiedValue *= 1000;
                    else if (ParseOhmMode(Convert.ToString(inputBytes[13], 2).PadLeft(8, '0')) == "M") RectifiedValue *= 1000000;
                }
                else if (UnitOfMeasure == "F")
                {
                    if (ParseNano(Convert.ToString(inputBytes[3], 2).PadLeft(8, '0').Substring(0, 4)))
                    {
                        Value += (" nF");
                        RectifiedValue /= 1000000000;
                    }
                    else Value += (" " + ParseSub(Convert.ToString(inputBytes[13], 2).PadLeft(8, '0')) + "F");
                }
                else Value += (" " + ParseSub(Convert.ToString(inputBytes[13], 2).PadLeft(8, '0')) + UnitOfMeasure);
                if (Parse10(Convert.ToString(inputBytes[10], 2).PadLeft(8, '0').Substring(0, 4)) == 99)
                    IsOutOfRange = true;
                
                // Setting AC/DC and Auto
                if ((UnitOfMeasure == "A") || (UnitOfMeasure == "V"))
                {
                    if (ParseACDC(Convert.ToString(inputBytes[1], 2).PadLeft(8, '0')) == "AC")
                    {
                        IsAC = true;
                        IsDC = false;
                    }
                    else if (ParseACDC(Convert.ToString(inputBytes[1], 2).PadLeft(8, '0')) == "DC")
                    {
                        IsDC = true;
                        IsAC = false;
                    }
                }
                if (IsAuto(Convert.ToString(inputBytes[1], 2).PadLeft(8, '0')))
                    IsAutoSub = true;
                else IsAutoSub = false;
                // Setting Rel and HOLD
                IsRel = ParseRel(Convert.ToString(inputBytes[1], 2).PadLeft(8, '0'));
                if (ParseHold(Convert.ToString(inputBytes[1], 2).PadLeft(8, '0')) && !IsRel)
                    IsHold = true;
                else if (ParseHold(Convert.ToString(inputBytes[1], 2).PadLeft(8, '0')) && IsRel)
                    IsHold = false;
                else if (!ParseHold(Convert.ToString(inputBytes[1], 2).PadLeft(8, '0')) && IsRel)
                    IsHold = true;
                else if (!ParseHold(Convert.ToString(inputBytes[1], 2).PadLeft(8, '0')) && !IsRel)
                    IsHold = false;
                //Setting OUT OF RANGE
                if (Parse10(Convert.ToString(inputBytes[10], 2).PadLeft(8, '0').Substring(0, 4)) == 99)
                    IsOutOfRange = true;
                else IsOutOfRange = false;
                //Setting extended Unit of Measure name
                if (ParseMode(Convert.ToString(inputBytes[9], 2).PadLeft(8, '0')) == "A")
                {
                    LongUnitOfMeasure = "Amperes";
                }
                else if (ParseMode(Convert.ToString(inputBytes[9], 2).PadLeft(8, '0')) == "V")
                {
                    LongUnitOfMeasure = "Volts";
                }
                else if (ParseMode(Convert.ToString(inputBytes[9], 2).PadLeft(8, '0')) == "°C")
                {
                    LongUnitOfMeasure = "Celsius Degrees";
                }
                else if (ParseMode(Convert.ToString(inputBytes[9], 2).PadLeft(8, '0')) == "°F")
                {
                    LongUnitOfMeasure = "Fahrenheit Degrees";
                }
                else if (ParseMode(Convert.ToString(inputBytes[9], 2).PadLeft(8, '0')) == "Hz")
                {
                    LongUnitOfMeasure = "Hertz";
                }
                else if (ParseMode(Convert.ToString(inputBytes[9], 2).PadLeft(8, '0')) == "F")
                {
                    LongUnitOfMeasure = "Farad";
                }
                else if (ParseMode(Convert.ToString(inputBytes[9], 2).PadLeft(8, '0')) == "Ω")
                {
                    LongUnitOfMeasure = "Ohm";
                }
                if(ParseMaxMin(Convert.ToString(inputBytes[3], 2).PadLeft(8, '0').Substring(4, 4))==1)
                {
                    IsMax = true;
                    IsMin = false;
                } else if (ParseMaxMin(Convert.ToString(inputBytes[3], 2).PadLeft(8, '0').Substring(4, 4)) == 2)
                {
                    IsMax = false;
                    IsMin = true;
                } else
                {
                    IsMax = false;
                    IsMin = false;
                }
            }
            else
            {
                throw new System.ArgumentException("You must first set data to process through the inputBytes Byte[] variable", "inputBytes");
            }
        }

        // BYTE DECODE FUNCTIONS
        private int Parse7(string input)
        {
            if (input == "1000")
            {
                return 0;
            }
            else if (input == "0000")
            {
                return 1;
            }
            else if (input == "1100")
            {
                return 2;
            }
            else if (input == "0100")
            {
                return 3;
            }
            else if (input == "1010")
            {
                return 4;
            }
            else if (input == "0010")
            {
                return 5;
            }
            else if (input == "1110")
            {
                return 6;
            }
            else if (input == "0110")
            {
                return 7;
            }
            else if (input == "1001")
            {
                return 8;
            }
            else if (input == "0001")
            {
                return 9;
            }
            else return 0;
        }
        private int Parse10(string input)
        {
            if (input == "0110")
            {
                return 0;
            }
            else if (input == "1110")
            {
                return 1;
            }
            else if (input == "1010")
            {
                return 2;
            }
            else if (input == "0010")
            {
                return 3;
            }
            else if (input == "1000")
            {
                return 4;
            }
            else if (input == "0000")
            {
                return 5;
            }
            else if (input == "1100")
            {
                return 6;
            }
            else if (input == "0100")
            {
                return 7;
            }
            else if (input == "0111")
            {
                return 8;
            }
            else if (input == "1111")
            {
                return 9;
            } else if (input == "1011")
            {
                return 99;
            }
            else return 0;
        }
        private int Parse4(string input)
        {
            if (input == "0111")
            {
                return 0;
            }
            else if (input == "1111")
            {
                return 1;
            }
            else if (input == "1011")
            {
                return 2;
            }
            else if (input == "0011")
            {
                return 3;
            }
            else if (input == "1001")
            {
                return 4;
            }
            else if (input == "0001")
            {
                return 5;
            }
            else if (input == "1101")
            {
                return 6;
            }
            else if (input == "0101")
            {
                return 7;
            }
            else if (input == "1000")
            {
                return 8;
            }
            else if (input == "0000")
            {
                return 9;
            }
            else return 0;
        }
        private int Parse11(string input)
        {
            if (input == "0111")
            {
                return 0;
            }
            else if (input == "1111")
            {
                return 1;
            }
            else if (input == "1011")
            {
                return 2;
            }
            else if (input == "0011")
            {
                return 3;
            }
            else if (input == "1001")
            {
                return 4;
            }
            else return 0;
        }
        private int CommaPos(string input)
        {
            if (input == "0000")
            {
                return 3;
            }
            else if (input == "1100")
            {
                return 2;
            }
            else if (input == "1010")
            {
                return 1;
            }
            else return 0;
        }
        private Double ParseSign(string input)
        {
            if (input == "01")
            {
                return (-1);
            }
            else return 1;
        }
        private string ParseSub(string input)
        {
            if (input == "01101010")
            {
                return "μ";
            }
            else if (input == "01101011")
            {
                return "m";
            }
            else return "";
        }
        private string ParseMode(string input)
        {
            if (input == "01101010")
            {
                return "V";
            }
            else if (input == "01101011")
            {
                return "A";
            }
            else if (input == "10101001")
            {
                return "°C";
            }
            else if (input == "11101001")
            {
                return "°F";
            }
            else if (input == "01111001")
            {
                return "Hz";
            }
            else if (input == "10001001")
            {
                return "F";
            }
            else if (input == "01101101")
            {
                return "Ω";
            }
            else return "";
        }
        private string ParseACDC(string input)
        {
            if (input.Substring(4, 1) == "1")
                return "AC";
            else if (input.Substring(4, 1) == "0")
                return "DC";
            else return "";
        }
        private bool ParseHold(string input)
        {
            if (input.Substring(1, 1) == "1")
                return false;
            else if (input.Substring(1, 1) == "0")
                return true;
            else return false;
        }
        private Boolean IsAuto(string input)
        {
            if (input.Substring(5, 1) == "1")
                return true;
            else return false;
        }
        private string ParseOhmMode(string input)
        {
            if (input == "01101101") return "k";
            else if (input == "01110001") return "M";
            else return "";
        }
        private bool ParseNano(string input)
        {
            if (input == "1010")
            {
                return true;
            }
            else return false;
        }
        private int ParseMaxMin(string input)
        {
            if (input == "1000") return 1;
            else if (input == "1100") return 2;
            else return 0;
        }
        private bool ParseRel(string input)
        {
            if (input.Substring(2, 1) == "0") return true;
            else return false;
        }
    }
    public class executeMath
    {
        public double DeltaQ;
        public double Pow;
        public executeMath()
        {
            DeltaQ = Pow = 0;
        }
        public void GetDQandPow(double T1, double T2, double t1, double t2, double a, double b, double c, double d, double evar)
        {
            DeltaQ = (a / 5) * (Math.Pow(T2, 5) - Math.Pow(T1, 5)) + (b / 4) * (Math.Pow(T2, 4) - Math.Pow(T1, 4)) + (c / 3) * (Math.Pow(T2, 3) - Math.Pow(T1, 3)) + (d / 2) * (Math.Pow(T2, 2) - Math.Pow(T1, 2)) + evar * (T2-T1);
            Pow = DeltaQ / (t2 - t1);
        }
    }
}
